package de.tu_darmstadt.gdi1.xcom.controller.ai;

import java.util.LinkedList;
import java.util.List;

import de.tu_darmstadt.gdi1.framework.utils.Point;
import de.tu_darmstadt.gdi1.xcom.model.XcomTeam;
import de.tu_darmstadt.gdi1.xcom.model.elements.GameElement;
import de.tu_darmstadt.gdi1.xcom.model.elements.Human;
import de.tu_darmstadt.gdi1.xcom.model.elements.Mob;

public class XcomAIGame {

	private XcomTeam team1;
	private XcomTeam team2;
	
	private boolean team1IsActive;
	
	private int playedRounds;
	public boolean isTeam1IsActive() {
		return team1IsActive;
	}

	public void setTeam1IsActive(boolean team1IsActive) {
		this.team1IsActive = team1IsActive;
	}

	public int getPlayedRounds() {
		return playedRounds;
	}

	public void setPlayedRounds(int playedRounds) {
		this.playedRounds = playedRounds;
	}

	public int getMaxRounds() {
		return maxRounds;
	}

	public void setMaxRounds(int maxRounds) {
		this.maxRounds = maxRounds;
	}

	private int maxRounds;
	
	private List<GameElement>[][] gameField;
	
	public XcomAIGame(List<GameElement>[][] gameField){
		this.gameField = gameField;
	}
	
	public void setTeam(XcomTeam team, boolean setTeam1){
		if(setTeam1)
			team1 = team;
		else
			team2 = team;
	}
	
	public void setActiveTeam(boolean team1IsActive){
		this.team1IsActive = team1IsActive;
	}
	
	public void setTeam2UseAi(int mode) {
		switch (mode) {
		case 0:
			team2.setAI(new XcomSimpleAI());
			break;
		case 1:
			team2.setAI(new XcomMediumAI());
			break;
		default:
			team2.setAI(new XcomSimpleAI());
		}
	}
	
	public XcomTeam getActiveTeam(){
		if(team1IsActive)
			return team1;
		return team2;
	}
	
	public List<Mob> getActiveTeamMobs(){
		return getMobs(team1IsActive);
	}
	
	public List<Mob> getEnemyTeamMobs(){
		return getMobs(!team1IsActive);
	}
	
	private Mob getMobOnPosition(Point pos) {
		List<GameElement> elementsOnSelectedField = gameField[pos.getX()][pos.getY()];
		if(elementsOnSelectedField.size() > 1 && elementsOnSelectedField.get(elementsOnSelectedField.size() - 1) instanceof Mob)
			// TODO: casten ist evtl. problematisch...
			return (Mob) elementsOnSelectedField.get(elementsOnSelectedField.size() - 1);
		else throw new IllegalArgumentException("an der Position befindet sich kein Mob" + pos.getX() + ";" + pos.getY());
	}
	
	private List<Mob> getMobs(boolean team1) {
		List<Mob> returnList = new LinkedList<Mob>();
		List<Point> positions;
		if(team1)
			positions = this.team1.getMobPositions();
		else
			positions = this.team2.getMobPositions();
		
		for(Point currentPoint : positions) {
			returnList.add(getMobOnPosition(currentPoint));
		}
		return returnList;
	}
	
	public List<GameElement> getElementsAt(Point pos){
		return gameField[pos.getX()][pos.getY()];
	}
	
	public int getMapWidth() {
		return gameField.length;	
	}
	
	public int getMapHeight() {
		return gameField[0].length;
	}
	
	public boolean blockedForAI(Point pos) {
		boolean result = false;
		
		for(GameElement ge : gameField[pos.getX()][pos.getY()]) {
			// humans appear to be passable
			result = result 
				|| (ge.isSolid() && (!ge.getClass().equals(Human.class)))
				|| ge.isWall();
		}
		
		return result;
	}
	
	public boolean containsHuman(Point pos) {
		boolean result = false;
		for(GameElement ge : gameField[pos.getX()][pos.getY()]) {
			result = result || ge.getClass().equals(Human.class);
		}
		return result;
	}
}
